package com.gel.codegeneration.core.handler;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.gel.codegeneration.ai.model.enums.StreamMessageTypeEnum;
import com.gel.codegeneration.ai.model.message.AiResponseMessage;
import com.gel.codegeneration.ai.model.message.StreamMessage;
import com.gel.codegeneration.ai.model.message.ToolExecutedMessage;
import com.gel.codegeneration.ai.model.message.ToolRequestMessage;
import com.gel.codegeneration.ai.tools.BaseTool;
import com.gel.codegeneration.ai.tools.ToolManager;
import com.gel.codegeneration.common.constant.AppConstant;
import com.gel.codegeneration.common.enums.ChatHistoryMessageTypeEnum;
import com.gel.codegeneration.core.builder.VueProjectBuilder;
import com.gel.codegeneration.model.entity.User;
import com.gel.codegeneration.service.ChatHistoryService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.HashSet;
import java.util.Set;


/**
 * @BelongsProject: code-generation-platform
 * @BelongsPackage: com.gel.codegeneration.core.handler
 * @Author: gel
 * @CreateTime: 2025-08-24  18:20
 * @Description: TODO tokenStream的json消息流处理器
 * @Version: 1.0
 */
@Slf4j
@Component
public class JsonMessageStreamHandler {
    @Resource
    private VueProjectBuilder vueProjectBuilder;
    @Resource
    private ToolManager toolManager;
    public Flux<String> handle(Flux<String> originFlux, ChatHistoryService chatHistoryService, Long appId, User loginUser) {
        //收集数据用于后端记忆格式
        StringBuffer aiResponse = new StringBuffer();
        //跟踪已经使用过的工具，判断是否第一次调用
        Set<String>  seenTools=new HashSet<>();
        return originFlux.map(
                chunk->{
                    //收集ai响应的内容
                    return  handleJsonMessageChunk(chunk,aiResponse,seenTools);
                }).doOnComplete(()->{
            //存储ai回复到mysql
            chatHistoryService.addChatMessage(appId,aiResponse.toString(), ChatHistoryMessageTypeEnum.AI.getValue(), loginUser.getId());
            //异步构建项目
            String projectDir= AppConstant.CODE_OUTPUT_ROOT_DIR+"/vue_project_"+appId;
            vueProjectBuilder.buildVueProjectAsync(projectDir);
        }).doOnError(e->{
            String errorMessage = "ai回复失败"+e.getMessage();
            chatHistoryService.addChatMessage(appId,errorMessage, ChatHistoryMessageTypeEnum.AI.getValue(), loginUser.getId());
        });
    }

    /** 解析并收集TokenStream的json消息块
     * @param chunk
     * @param aiResponse
     * @param seenTools
     * @return
     */
    private String handleJsonMessageChunk(String chunk, StringBuffer aiResponse, Set<String> seenTools) {
        //解析json
        StreamMessage streamMessage = JSONUtil.toBean(chunk, StreamMessage.class);
        StreamMessageTypeEnum enumByValue = StreamMessageTypeEnum.getEnumByValue(streamMessage.getType());
        switch ( enumByValue){
            case AI_RESPONSE->{
                AiResponseMessage aiResponseMessage = JSONUtil.toBean(chunk, AiResponseMessage.class);
                String data = aiResponseMessage.getData();
                //拼接响应结果
                aiResponse.append(data);
                return data;
            }
            case TOOL_REQUEST->{
                ToolRequestMessage toolRequestMessage = JSONUtil.toBean(chunk, ToolRequestMessage.class);
                String toolId = toolRequestMessage.getId();
                String toolName = toolRequestMessage.getName();
                //检查是否是第一次看到这个工具id
                if(toolId!=null&&!seenTools.contains(toolId)){
                    //只有第一次调用这个工具的时候才记录id并返回工具信息
                    seenTools.add(toolId);
                    BaseTool tool = toolManager.getTool(toolName);
                    return tool.generateToolRequestResponse();

                }else {
                    return "";
                }

            }
            case TOOL_EXECUTED -> {
                ToolExecutedMessage toolExecutedMessage = JSONUtil.toBean(chunk, ToolExecutedMessage.class);
                JSONObject jsonObject = JSONUtil.parseObj(toolExecutedMessage.getArguments());
                String toolName = toolExecutedMessage.getName();
                BaseTool tool = toolManager.getTool(toolName);
                String result = tool.generateToolExecutedResult(jsonObject);
                String output = String.format("\n\n%s\n\n```", result);
                aiResponse.append( output);
                return output;

            }default -> {
                log.error("不支持的消息类型",enumByValue);
                return "";
            }



        }





    }
}
